package cn.wgx.module.mind.websocket.web;

import cn.wgx.common.base.BaseLogger;
import cn.wgx.module.mind.websocket.entity.BaseMessage;
import cn.wgx.module.mind.websocket.entity.MessageType;
import cn.wgx.module.mind.websocket.entity.WSPrincipal;
import cn.wgx.module.mind.websocket.util.OnlineUserTool;
import cn.wgx.module.mind.websocket.util.RoomMsgSender;
import cn.wgx.module.mind.websocket.util.SWLockUtil;
import com.alibaba.fastjson.JSONObject;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.MessageHeaders;
import org.springframework.messaging.handler.annotation.*;
import org.springframework.messaging.simp.SimpMessagingTemplate;
import org.springframework.messaging.simp.annotation.SendToUser;
import org.springframework.messaging.simp.stomp.StompHeaderAccessor;
import org.springframework.messaging.support.MessageHeaderAccessor;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import java.security.Principal;
import java.util.Map;

import static cn.wgx.common.util.ResponseDataUtil.returnData;

/**
 * websocket 聊天室接口
 */
@Api(description = "WebSocket聊天室获取请求地址")
@Controller
@RequestMapping("/chatOnline")
public class WSController extends BaseLogger {

    @Autowired
    private SimpMessagingTemplate simpMessagingTemplate;

    //发送地址前加统一前缀 /app

    //公聊发送请求地址
    public final static String url_req_public_room = "/public/{room}";
    //公聊订阅地址-
    public final static String url_sub_public_room = "/topic/public.{room}";
    //私聊发送地址
    public final static String url_req_person_room = "/private/{room}";
    //私聊订阅地址
    public final static String url_sub_person_room = "/topic/private.{room}";

    /**
     * websocket
     * 广播消息，不指定用户，所有订阅此的用户都能收到消息
     * MessageMapping: 为前端消息发送地址
     * SendTo: 表示订阅地址,所有送到MessageMapping的消息全部发送至此订阅用户. 如不写,则订阅地址默认为MessageMapping地址
     * 完全参数展示
     * jsonObject ex: {}
     */
    @MessageMapping(url_req_public_room)
    @SendTo(url_sub_public_room)
    public BaseMessage sendAllUser(@DestinationVariable String room,
                                   @Payload Object payload,
                                   BaseMessage jsonObject,
                                   @Headers MessageHeaders messageHeaders,
                                   MessageHeaderAccessor messageHeaderAccessor,
                                   Principal principal) {
        if (logger.isDebugEnabled()) {
            logger.debug("房间号：" + room + " " + jsonObject.toJSONOString());
        }
        jsonObject.setRoomId(room);
        //事件处理
        boolean b = processEvent(jsonObject, room, (WSPrincipal) principal);
        if (!b) {
            return null;
        }
        //代码写法: 发送指定订阅地址
        //simpMessageSendingOperations.convertAndSend("/topic/shouts", helloMessage);
        return RoomMsgSender.wrap(jsonObject, principal);
    }


    /**
     * 指定用户发送消息
     *
     * @param stompHeaderAccessor
     */
    @MessageMapping(url_req_person_room)
    public void sendUser(@DestinationVariable String room,
                         BaseMessage jsonObject,
                         StompHeaderAccessor stompHeaderAccessor,
                         Principal principal) {

        if (logger.isDebugEnabled()) {
            logger.debug("房间号: " + room + "接收到私聊消息：" + jsonObject.toJSONOString());
        }
        //事件处理
        boolean b = processEvent(jsonObject, room, (WSPrincipal) principal);
        if (!b) {
            return;
        }
        String replace = url_sub_person_room.replace("{room}", room == null ? "" : room);
        String toUser = jsonObject.getToUser();
        if (null != toUser) {
            simpMessagingTemplate.convertAndSendToUser(toUser, replace, RoomMsgSender.wrap(jsonObject, principal));
        }

    }


    /**
     * 只能发送给自己,相当于一次请求
     * MessageMapping: 为前端消息发送地址
     * SendTo: 表示订阅地址,所有送到MessageMapping的消息全部发送至此订阅用户. 如不写,则订阅地址默认为MessageMapping地址
     * @param message
     * @return
     */
    @MessageMapping("/toMe")
    @SendToUser("/msg")
    public BaseMessage userStomp(BaseMessage message, StompHeaderAccessor stompHeaderAccessor) {
        Principal user = stompHeaderAccessor.getUser();
        logger.info("认证的名字是：{}，收到的消息是：{}", user.getName(), message.getContent());
        return message;
    }


    private JSONObject jsonObject = null;

    @ApiOperation("获取公共聊天室和私人聊天室请求地址")
    @ResponseBody
    @RequestMapping(value = "getRoomPath", method = RequestMethod.GET)
    public Object getRoomPath() {
        if (jsonObject == null) {
            jsonObject = new JSONObject();
            jsonObject.put("url_req_person_room", "/app" + url_req_person_room);
            jsonObject.put("url_sub_person_room", url_sub_person_room);
            jsonObject.put("url_req_public_room", "/app" + url_req_public_room);
            jsonObject.put("url_sub_public_room", url_sub_public_room);
        }
        return returnData(jsonObject);
    }


    @ApiOperation(value = "获取公共聊天室所有用户", notes = "最多获取100人")
    @ResponseBody
    @RequestMapping(value = "getRoomUsers/{roomId}", method = RequestMethod.GET)
    public Object getUsers(@PathVariable String roomId) {
//        return returnData(OnlineUserTool.getUsers(url_sub_public_room.replace("{room}", roomId), 0, 0));
        return returnData(OnlineUserTool.getUsers(roomId, 0, 0));
    }

    @ApiOperation(value = "获取事件关键字", notes = " //事件\n" +
            "    //用户加入\n" +
            "    EVENT_USER_JOIN,\n" +
            "    //用户退出\n" +
            "    EVENT_USER_LEFT,\n" +
            "\n" +
            "    //管理员操作事件\n" +
            "    //踢出\n" +
            "    EVENT_USER_KICK,\n" +
            "    //禁言某人\n" +
            "    EVENT_USER_SILENT,\n" +
            "    //解禁禁言某人\n" +
            "    EVENT_USER_UNSILENT,\n" +
            "    //全体禁言\n" +
            "    EVENT_ALL_SILENT,\n" +
            "    //全体解禁\n" +
            "    EVENT_ALL_LIBERATE,\n" +
            "\n" +
            "    //添加管理员\n" +
            "    EVENT_ADD_ADMIN")
    @ResponseBody
    @RequestMapping(value = "getEventKey", method = RequestMethod.GET)
    public Object getEvent() {
        return returnData(MessageType.values());
    }


    //事件处理器, 如果返回false则不需要返回消息
    private boolean processEvent(BaseMessage jsonObject, String roomId, WSPrincipal currentPrincipal) {
        MessageType msgType = jsonObject.getMsgType();
        if (msgType != null) {
            switch (msgType) {
                //锁定
                case EVENT_SW_LOCK:
                    SWLockUtil.lock(roomId, jsonObject.getBeat_id().toString(), currentPrincipal);
                    break;
                //解锁
                case EVENT_SW_UNLOCK:
                    SWLockUtil.unlock(roomId, jsonObject.getBeat_id().toString(), currentPrincipal);
                    break;
                //获取全部锁定节点
                case EVENT_SW_GET_ALL:
                    Map<String, WSPrincipal> allLocks = SWLockUtil.getAllLocks(roomId, 0, 0);
                    jsonObject.setData(allLocks);
                    break;
                //获取指定节点是否锁定
                case EVENT_SW_GET_ONE:
                    SWLockUtil.getLockPrincipal(roomId, jsonObject.getBeat_id().toString());
                    break;
                default:
                    break;
            }
            return true;
        }
        return true;
    }
}